/**
*方法装饰者
*author diqye
*/
(function(root,factory){
	if (typeof exports === 'object') {
        // Node. 
        module.exports = factory.call(root);
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function(){ return factory.call(root) });
    } else {
        // Browser globals (root is window)
        window.utilfn = factory.call(root);
    }
}(this,function(){
	function utilfn(obj){
		return {
			//将Obj对象属性 copy到 obj2中有重复的覆盖 并反回 copy深度为一层
			copyTo:function(obj2){
				obj2 = obj2 || {};
				var result = {};
				for(var item in obj2){
					result[item] = obj2[item];
				}
				for(var item in obj){
					result[item] = obj[item];
				}
				return result;
			},
			isFunction:function(){
				return typeof obj == "function";
			}
		}
	}

	/* // instantiate
	* var options = { key: 'val' };
	* var instance = service( 'name', options );
	*/
	utilfn.decorator = function(type,baseProto){
		var registry = {},proto;

		var mixin = function mixin( key, val ){
			if ( typeof key === 'object' ){
				proto = utilfn(key).copyTo(proto);
				proto.type = type;
				return;
			}

			if ( key !== 'type' && utilfn( val ).isFunction() ){
				proto[ key ] = val;
			}
		};
		mixin(baseProto);

		var factory = function factory( name, parentName, decorator, cfg ){
			var instance
				,result
				,parent = proto
				,tmp
				;
			// set parent if specified
			if ( typeof parentName !== 'string' ){

				// ... otherwise reassign parameters
				cfg = decorator;
				decorator = parentName;

			} else {

				// extend the specified module
				parent = registry[ parentName ];

				if ( !parent ){

					throw 'Error: "' + parentName + '" ' + type + ' not defined';
				}

				parent = parent.prototype;
			}

			if ( typeof decorator === 'function' ){

				result = registry[ name ];

				if ( result ){
					var resultProto = decorator(result.prototype);
					result.prototype=utilfn(resultProto).copyTo(result.prototype);
					
				} else {
					// newly defined
					// store the new class
					result = registry[ name ] = function constructor( opts ){
						if (this.init){
							this.init( opts );
						}
					};
					var resultProto = decorator(parent);
					result.prototype = parent;
					result.prototype = utilfn(resultProto).copyTo(result.prototype);
				}

				result.prototype.type = type;
				result.prototype.name = name;
				
			} else {

				cfg = decorator || {};
				result = registry[ name ];
				if (!result){

					throw 'Error: "' + name + '" ' + type + ' not defined';
				}
			}

			if ( cfg ) {

				// create a new instance from the provided decorator
				return new result( cfg );
			}
		};

		factory.mixin = mixin;

		return factory;
	}




	return utilfn;
}));